//
// Created by shiminli on 2023/12/28.
//
#include "router.h"

CommonParameterName Router::parameterName;
CommonParameter Router::parsParameter(const hv::Json &body) {
    CommonParameter result;
    if (body[parameterName.arecode].is_number()){
        result.arecode = body[parameterName.arecode];
    }
    if (body[parameterName.platform].is_string()){
        result.platform = body[parameterName.platform];
    }
    return result;
}

void Router::Register(hv::HttpService& router){
    router.POST("/echo", [](const HttpContextPtr& ctx) {
        return ctx->send(ctx->body(), ctx->type());
    });

    // 发送验证码
    router.POST("/sendCode", [](const HttpContextPtr& ctx){
        hv::Json body = ctx->json();
        printRequest(ctx->url(), ctx->body());
        hv::Json result = hv::Json();
        long mobile = -1;
        if (body["mobile"].is_number()){
            mobile = body["mobile"];
        }
        CommonParameter commonParameter = parsParameter(body);
        if (commonParameter.arecode == -1 || commonParameter.platform.empty()){
            response_msg(ctx,result, 10001, "Please enter the common parameter");
            return HTTP_STATUS_BAD_REQUEST;
        }
        // 判断手机号和区号是不是真实的值
        if (commonParameter.arecode != 86){
            response_msg(ctx,result, 10001, "Please enter the correct area code");
            return HTTP_STATUS_BAD_REQUEST;
        }
        // 判断手机号格式
        if (!number::validatePhoneNumberWithRegex(to_string(mobile))){
            response_msg(ctx,result, 10002, "mobile format is incorrect");
            return HTTP_STATUS_BAD_REQUEST;
        }

        int verifyCode = number::genVerifyCode();

        // 准备要插入的数据
        time_t duration = time(0);
        VerifyCodes verifyCodes{};
        verifyCodes.phone_number = to_string(mobile);
        verifyCodes.platform = commonParameter.platform;
        verifyCodes.verify_code = to_string(verifyCode);
        verifyCodes.duration = duration;
        verifyCodes.used = 0;
        verifyCodes.create_time = number::timestamp();
        long ret = verify_codes::insert(verifyCodes);
        if (ret != 0){
            string msg = SQLHelper::getInstance()->getMysqlError();
            cout << "sql execute ret="<<ret << msg <<endl;
            response_msg(ctx,result, 10003, msg.c_str());
            return HTTP_STATUS_BAD_GATEWAY;
        }
        result = {
                {"verifyCode", verifyCode},
                {"id", number::genVerifyCode()},
        };
        response_msg(ctx,result, HTTP_STATUS_OK, "OK");
        return HTTP_STATUS_OK;
    });



    // 注册
    router.POST("/register", [](const HttpContextPtr& ctx) {
        hv::Json body = ctx->json();
        printRequest(ctx->url(), ctx->body());
        hv::Json result = hv::Json();

        CommonParameter commonParameter = parsParameter(body);
        if (commonParameter.arecode == -1 || commonParameter.platform.empty()){
            response_msg(ctx,result, 10001, "Please enter the common parameter");
            return HTTP_STATUS_BAD_REQUEST;
        }
        long mobile = -1;
        if (body["mobile"].is_number()){
            mobile = body["mobile"];
        }
        int verifyCode = -1;
        if (body["verifyCode"].is_number()){
            verifyCode = body["verifyCode"];
        }
        std::optional<VerifyCodes> verModel = verify_codes::queryByPhoneNumber(to_string(mobile));
        if (!verModel.has_value() || stoi(verModel->verify_code) != verifyCode){
            response_msg(ctx,result, 10003, "验证码错误");
            return HTTP_STATUS_BAD_GATEWAY;
        }
        time_t duration = time(0);
        if ((duration-verModel->duration) > 1800){
            response_msg(ctx,result, 10003, "验证码已超时 有效期30分钟");
            return HTTP_STATUS_BAD_GATEWAY;
        }
        // 更新为已使用
        verify_codes::updateUseByCode(verModel->verify_code);
        string msg;
        if (accounts::queryUserIdByPhoneNumber(to_string(mobile))){
            response_msg(ctx,result, 10003, "手机号已经存在 请使用新的手机号注册");
            return HTTP_STATUS_BAD_GATEWAY;
        }
        Accounts account{};
        account.account = to_string(mobile);
        account.password = dd_encryption::calculateMD5("123123");
        account.phone_number = account.account;
        account.area_code = to_string(commonParameter.arecode);
        account.nickname = to_string(mobile).replace(3, 4, "****");
        account.create_time = number::timestamp();
        account.change_time = account.create_time;
        account.birth_time = account.create_time;
        int ret = accounts::insert(account);
        if (!ret){
            msg = SQLHelper::getInstance()->getMysqlError();
            response_msg(ctx,result, 10005, msg.c_str());
            return HTTP_STATUS_BAD_GATEWAY;
        }
        response_msg(ctx,result, HTTP_STATUS_OK, "OK");
        return HTTP_STATUS_OK;
    });

    // 登录
    router.POST("/login", [](const HttpContextPtr& ctx) {
        hv::Json body = ctx->json();
        printRequest(ctx->url(), ctx->body());
        hv::Json result = hv::Json();

        CommonParameter commonParameter = parsParameter(body);
        if (commonParameter.arecode == -1 || commonParameter.platform.empty()) {
            response_msg(ctx, result, 10001, "Please enter the common parameter");
            return HTTP_STATUS_BAD_REQUEST;
        }
        long mobile = -1;
        if (body["mobile"].is_number()) {
            mobile = body["mobile"];
        }
        string pwd;
        if (body["pwd"].is_string()) {
            pwd = body["pwd"];
        }
        std::optional<Accounts> info = accounts::queryByPhoneNumber(to_string(mobile));
        if (!info.has_value()){
            response_msg(ctx,result, 10005, "请先注册账号");
            return HTTP_STATUS_BAD_GATEWAY;
        }
        if (pwd != info->password){
            response_msg(ctx,result, 10005, "密码错误");
            return HTTP_STATUS_BAD_GATEWAY;
        }
        Accounts account = info.value();
        hv::Json accJson = hv::Json();
        account.to_json(accJson);
        dd_token dt;
        string token = dt.generateToken(account.account);
        size_t pos = token.find(".");
//        std::string payloadStr = token.substr(0, pos);
        std::string signature = token.substr(pos + 1);
        accJson["token"] = signature;
        result["data"] = accJson;
        DDRedis::getInstance()->set(dd_encryption::calculateMD5(account.phone_number), token);
        response_msg(ctx,result, HTTP_STATUS_OK, "OK");
        return HTTP_STATUS_OK;
    });


}